import request from 'sync-request-curl';
import config from './config.json';
import { data } from './dataStore';
import { adminAuthLogout, adminAuthRegister } from './auth';
import { token } from 'morgan';

const port = config.port;
const url = config.url;

describe('Update thumbnail', () => {
    test('Normal run', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/admin/quiz/1/thumbnail`,
            {
                headers: {
                    'Authorization': `Bearer aswe2` // 使用 Bearer 方案添加 token
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(401);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({});
    });

    test('The imgUrl does not end with one of the following filetypes: jpg, jpeg, png', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/admin/quiz/1/thumbnail`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                json: {
                    "imgUrl": "http://example.com/image.gif"
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'The imgUrl does not end with one of the following filetypes (case insensitive): jpg, jpeg, png'
        });
    });

    test('The imgUrl does not begin with "http://" or "https://"', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/admin/quiz/1/thumbnail`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                json: {
                    "imgUrl": "ftp://example.com/image.jpg"
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'The imgUrl does not begin with "http://" or "https://"'
        });
    });

    test('Valid token is provided, but user is not an owner of this quiz', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/admin/quiz/2/thumbnail`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(403);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Valid token is provided, but user is not an owner of this quiz'
        });
    });
});


describe('View active and inactive quiz sessions', () => {
    test('Normal run', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/sessions`,
            {
                headers: {
                    'Authorization': `Bearer aswe2` // Using Bearer scheme for token
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toMatchObject({
            sessions: expect.any(Array) // Assuming the response should contain an array of sessions
        });
    });

    test('Token is empty or invalid (does not refer to valid logged in user session)', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/sessions`,
            {
                headers: {
                    'Authorization': `Bearer ` // Intentionally left empty or could be invalid
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(401);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Token is empty or invalid (does not refer to valid logged in user session)'
        });
    });

    test('Valid token is provided, but user is not an owner of this quiz', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/2/sessions`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(403);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Valid token is provided, but user is not an owner of this quiz'
        });
    });
});


describe('Start Quiz Session', () => {

    test('autoStartNum is a number greater than 50', () => {
        const res = request(
            'POST',
            `${url}:${port}/v1/admin/quiz/1/session/start`,
            {
                headers: {
                    'Authorization': `Bearer validToken`
                },
                json: {
                    "autoStartNum": 51
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'autoStartNum is a number greater than 50'
        });
    });

    test('A maximum of 10 sessions that are not in END state currently exist for this quiz', () => {
        const res = request(
            'POST',
            `${url}:${port}/v1/admin/quiz/1/session/start`,
            {
                headers: {
                    'Authorization': `Bearer validToken`
                },
                json: {
                    "autoStartNum": 5
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'A maximum of 10 sessions that are not in END state currently exist for this quiz'
        });
    });

    test('The quiz does not have any questions in it', () => {
        const res = request(
            'POST',
            `${url}:${port}/v1/admin/quiz/1/session/start`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                json: {
                    "autoStartNum": 3
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'The quiz does not have any questions in it'
        });
    });

    test('The quiz is in trash', () => {
        const res = request(
            'POST',
            `${url}:${port}/v1/admin/quiz/1/session/start`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                json: {
                    "autoStartNum": 3
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'The quiz is in trash'
        });
    });

    test('Token is empty or invalid (does not refer to valid logged in user session)', () => {
        const res = request(
            'POST',
            `${url}:${port}/v1/admin/quiz/1/session/start`,
            {
                headers: {
                    'Authorization': `Bearer sdfasdfe`  // Empty token
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(401);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Token is empty or invalid (does not refer to valid logged in user session)'
        });
    });

    test('Valid token is provided, but user is not an owner of this quiz', () => {
        const res = request(
            'POST',
            `${url}:${port}/v1/admin/quiz/2/session/start`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(403);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Valid token is provided, but user is not an owner of this quiz'
        });
    });

    test('Normal run', () => {
        const res = request(
            'POST',
            `${url}:${port}/v1/admin/quiz/1/session/start`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                json: {
                    "autoStartNum": 3
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            message: 'Session started successfully'
        });
    });

});

describe('Modify Quiz Session', () => {

    test('Session Id does not refer to a valid session within this quiz', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/admin/quiz/1/session/invalidSessionId`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                json: {
                    "action": "START"
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session Id does not refer to a valid session within this quiz'
        });
    });

    test('Action provided is not a valid Action enum', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/admin/quiz/1/session/1`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                json: {
                    "action": "INVALID_ACTION"
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Action provided is not a valid Action enum'
        });
    });

    test('Action enum cannot be applied in the current state', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/admin/quiz/1/session/1`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                json: {
                    "action": "END"
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Action enum cannot be applied in the current state'
        });
    });

    test('Valid token is provided, but user is not an owner of this quiz', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/admin/quiz/2/session/1`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(403);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Valid token is provided, but user is not an owner of this quiz'
        });
    });

    test('Token is empty or invalid (does not refer to valid logged in user session)', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/admin/quiz/1/session/1`,
            {
                headers: {
                    'Authorization': `Bearer sadasd`  // Empty or invalid token
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(401);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Token is empty or invalid (does not refer to valid logged in user session)'
        });
    });

    test('Normal run', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/admin/quiz/1/session/1`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                json: {
                    "action": "START"
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({});  // Assuming no specific return object is mentioned
    });

});



describe('Access Quiz Session Details', () => {

    test('Normal run', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/session/1`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                json: {
                    "action": "START"
                },
                timeout: 100
            }
        );
    
        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            "state": "LOBBY",
            "atQuestion": 3,
            "players": [
              "Hayden"
            ],
            "metadata": {
              "quizId": 5546,
              "name": "This is the name of the quiz",
              "timeCreated": 1683019484,
              "timeLastEdited": 1683019484,
              "description": "This quiz is so we can have a lot of fun",
              "numQuestions": 1,
              "questions": [
                {
                  "questionId": 5546,
                  "question": "Who is the Monarch of England?",
                  "duration": 4,
                  "thumbnailUrl": "http://google.com/some/image/path.jpg",
                  "points": 5,
                  "answers": [
                    {
                      "answerId": 2384,
                      "answer": "Prince Charles",
                      "colour": "red",
                      "correct": true
                    }
                  ]
                }
              ],
              "duration": 44,
              "thumbnailUrl": "http://google.com/some/image/path.jpg"
            }
          });  // Assuming no specific return object is mentioned


    });

    test('Session Id does not refer to a valid session within this quiz', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/session/invalidSessionId`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session Id does not refer to a valid session within this quiz'
        });
    });

    test('Token is empty or invalid (does not refer to valid logged in user session)', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/session/1`,
            {
                headers: {
                    'Authorization': `Bearer asdad`  // Intentionally left empty or invalid
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(401);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Token is empty or invalid (does not refer to valid logged in user session)'
        });
    });

    test('Valid token is provided, but user is not an owner of this quiz', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/2/session/1`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(403);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Valid token is provided, but user is not an owner of this quiz'
        });
    });

});



describe('Retrieve Quiz Session Results', () => {

    test('Session Id does not refer to a valid session within this quiz', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/session/invalidSessionId/results`,
            {
                headers: {
                    'Authorization': `Bearer validToken`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session Id does not refer to a valid session within this quiz'
        });
    });

    test('Session is not in FINAL_RESULTS state', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/session/1/results`,
            {
                headers: {
                    'Authorization': `Bearer validToken`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session is not in FINAL_RESULTS state'
        });
    });

    test('Token is empty or invalid (does not refer to valid logged in user session)', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/session/1/results`,
            {
                headers: {
                    'Authorization': `Bearer `  // Intentionally left empty or could be invalid
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(401);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Token is empty or invalid (does not refer to valid logged in user session)'
        });
    });

    test('Valid token is provided, but user is not an owner of this quiz', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/session/1/results`,
            {
                headers: {
                    'Authorization': `Bearer validTokenButNotOwner`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(403);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Valid token is provided, but user is not an owner of this quiz'
        });
    });

    test('Normal run', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/session/1/results`,
            {
                headers: {
                    'Authorization': `Bearer validToken`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        // Assuming the expected response should detail the final results, mocked below
        expect(bodyObj).toMatchObject({
            results: {
                sessionStatus: 'FINAL_RESULTS',
                scores: [
                    { player: "Player1", score: 100 },
                    { player: "Player2", score: 90 }
                ]
            }
        });
    });

});


describe('Retrieve Quiz Session Results CSV', () => {

    test('Session Id does not refer to a valid session within this quiz', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/session/invalidSessionId/results/csv`,
            {
                headers: {
                    'Authorization': `Bearer aswe2`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session Id does not refer to a valid session within this quiz'
        });
    });

    test('Session is not in FINAL_RESULTS state', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/session/1/results/csv`,
            {
                headers: {
                    'Authorization': `Bearer validToken`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session is not in FINAL_RESULTS state'
        });
    });

    test('Token is empty or invalid (does not refer to valid logged in user session)', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/session/1/results/csv`,
            {
                headers: {
                    'Authorization': `Bearer ` // Intentionally left empty or could be invalid
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(401);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Token is empty or invalid (does not refer to valid logged in user session)'
        });
    });

    test('Valid token is provided, but user is not an owner of this quiz', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/session/1/results/csv`,
            {
                headers: {
                    'Authorization': `Bearer validTokenButNotOwner`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(403);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Valid token is provided, but user is not an owner of this quiz'
        });
    });

    test('Normal run', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/admin/quiz/1/session/1/results/csv`,
            {
                headers: {
                    'Authorization': `Bearer validToken`
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        // Assuming the expected response should include CSV data or similar confirmation
        expect(bodyObj).toMatchObject({
            message: 'CSV data retrieved successfully'
        });
    });

});



describe('Player Join Operation', () => {

    test('Normal run', () => {
        const res = request(
            'POST',
            `${url}:${port}/v1/player/join`,
            {
                json: {
                    "sessionId": 234234,
                    "name": "Hayden Smith"
                },
                timeout: 100
            }
        );
    
        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        // Assuming the expected response should include CSV data or similar confirmation
        expect(bodyObj).toMatchObject({
            
        });
    });

    test('Name of user entered is not unique (compared to other users who have already joined)', () => {
        const res = request(
            'POST',
            `${url}:${port}/v1/player/join`,
            {
                json: {
                    "sessionId": 234234,
                    "name": "Hayden Smith"  // Assuming this name is already taken in this session
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Name of user entered is not unique (compared to other users who have already joined)'
        });
    });

    test('Session Id does not refer to a valid session', () => {
        const res = request(
            'POST',
            `${url}:${port}/v1/player/join`,
            {
                json: {
                    "sessionId": 999999,  // Assuming this is an invalid session ID
                    "name": "New Player"
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session Id does not refer to a valid session'
        });
    });

    test('Session is not in LOBBY state', () => {
        const res = request(
            'POST',
            `${url}:${port}/v1/player/join`,
            {
                json: {
                    "sessionId": 234234,  // Assuming this session is not in the LOBBY state
                    "name": "Another Player"
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session is not in LOBBY state'
        });
    });

});

describe('Status of guest player in session', () => {
    test('Session is not in LOBBY state', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}`,
            {
                timeout: 100
            }
        );
    
        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'If player ID does not exist'
        });
    });
    
    test('Session is not in LOBBY state', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}`,
            {
                timeout: 100
            }
        );
    
        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            "state": "LOBBY",
            "numQuestions": 1,
            "atQuestion": 3
        });
    });

});



describe('Player Access Quiz Question', () => {

    test('Session is not in LOBBY state', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/question/{questionposition}`,
            {
                timeout: 100
            }
        );
    
        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            "questionId": 5546,
            "question": "Who is the Monarch of England?",
            "duration": 4,
            "thumbnailUrl": "http://google.com/some/image/path.jpg",
            "points": 5,
            "answers": [
              {
                "answerId": 2384,
                "answer": "Prince Charles",
                "colour": "red"
              }
            ]
          });
    });

    test('If player ID does not exist', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/invalidPlayerId/question/1`,
            {
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Player ID does not exist'
        });
    });

    test('If question position is not valid for the session this player is in', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/question/invalidPosition`,  // Using an out of range or inappropriate position
            {
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Question position is not valid for the session this player is in'
        });
    });

    test('If session is not currently on this question', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/question/{questionposition}`,  // Assuming session is on a different question
            {
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session is not currently on this question'
        });
    });

    test('Session is in LOBBY, QUESTION_COUNTDOWN, or END state', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/question/{questionposition}`,  // Assuming the session is not in an active question state
            {
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session is in LOBBY, QUESTION_COUNTDOWN, or END state'
        });
    });

});




describe('Player Submit Answer Tests', () => {

    test('If question position is not valid for the session this player is in', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/player/{playerid}/question/{questionposition}/answer`,  // Using an out of range or inappropriate position
            {
                json: {
                    "answerIds": [
                        2384
                    ]
                },
                timeout: 100
            }
        );
    
        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({});
    });

    test('If player ID does not exist', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/player/invalidPlayerId/question/1/answer`,
            {
                json: {
                    "answerIds": [2384]
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Player ID does not exist'
        });
    });

    test('If question position is not valid for the session this player is in', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/player/{playerid}/question/invalidPosition/answer`,
            {
                json: {
                    "answerIds": [2384]
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Question position is not valid for the session this player is in'
        });
    });

    test('Session is not in QUESTION_OPEN state', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/player/{playerid}/question/{questionposition}/answer`,
            {
                json: {
                    "answerIds": [2384]
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session is not in QUESTION_OPEN state'
        });
    });

    test('If session is not yet up to this question', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/player/{playerid}/question/{questionposition}/answer`,
            {
                json: {
                    "answerIds": [2384]
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session is not yet up to this question'
        });
    });

    test('Answer IDs are not valid for this particular question', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/player/{playerid}/question/{questionposition}/answer`,
            {
                json: {
                    "answerIds": [9999]  // Assuming 9999 is not a valid answer ID for the question
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Answer IDs are not valid for this particular question'
        });
    });

    test('There are duplicate answer IDs provided', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/player/{playerid}/question/{questionposition}/answer`,
            {
                json: {
                    "answerIds": [2384, 2384]  // Duplicated answer ID
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'There are duplicate answer IDs provided'
        });
    });

    test('Less than 1 answer ID was submitted', () => {
        const res = request(
            'PUT',
            `${url}:${port}/v1/player/{playerid}/question/{questionposition}/answer`,
            {
                json: {
                    "answerIds": []  // No answer IDs submitted
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Less than 1 answer ID was submitted'
        });
    });

});




describe('Retrieve Question Results for Player', () => {

    test('normal run', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/question/{questionposition}/results`,
            {
                timeout: 100
            }
        );
    
        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            "questionId": 5546,
            "playersCorrectList": [
              "Hayden"
            ],
            "averageAnswerTime": 45,
            "percentCorrect": 54
          });
    });

    test('If player ID does not exist', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/invalidPlayerId/question/1/results`,
            {
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Player ID does not exist'
        });
    });

    test('If question position is not valid for the session this player is in', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/question/invalidPosition/results`,
            {
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Question position is not valid for the session this player is in'
        });
    });

    test('Session is not in ANSWER_SHOW state', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/question/{questionposition}/results`,
            {
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session is not in ANSWER_SHOW state'
        });
    });

    test('If session is not yet up to this question', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/question/{questionposition}/results`,
            {
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session is not yet up to this question'
        });
    });

});


describe('Retrieve Final Results for Player', () => {

    test('If session is not yet up to this question', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/results`,
            {
                timeout: 100
            }
        );
    
        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            "usersRankedByScore": [
              {
                "name": "Hayden",
                "score": 45
              }
            ],
            "questionResults": [
              {
                "questionId": 5546,
                "playersCorrectList": [
                  "Hayden"
                ],
                "averageAnswerTime": 45,
                "percentCorrect": 54
              }
            ]
          });
    });

    test('If player ID does not exist', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/invalidPlayerId/results`,
            {
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Player ID does not exist'
        });
    });

    test('Session is not in FINAL_RESULTS state', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/results`,
            {
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Session is not in FINAL_RESULTS state'
        });
    });

});


describe('Access Player Chat', () => {

    test('normal run', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/chat`,
            {
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            "messages": [
                {
                    "messageBody": "This is a message body",
                    "playerId": 5546,
                    "playerName": "Yuchao Jiang",
                    "timeSent": 1683019484
                }
            ]
        });
    });

    test('If player ID does not exist', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/invalidPlayerId/chat`,
            {
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Player ID does not exist'
        });
    });

});
describe('Player Chat Functionality Tests', () => {

    test('normal run', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/chat`,
            {
                json: {
                    "message": {
                        "messageBody": "Hello everyone! Nice to chat."
                    }
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(200);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({});
    });

    test('If player ID does not exist', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/invalidPlayerId/chat`,
            {
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Player ID does not exist'
        });
    });

    test('If message body is less than 1 character or more than 100 characters', () => {
        const res = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/chat`,
            {
                json: {
                    "message": {
                        "messageBody": ""  // Testing for less than 1 character
                    }
                },
                timeout: 100
            }
        );

        expect(res.statusCode).toBe(400);
        const bodyObj = JSON.parse(res.body as string);
        expect(bodyObj).toStrictEqual({
            error: 'Message body is less than 1 character or more than 100 characters'
        });

        const res2 = request(
            'GET',
            `${url}:${port}/v1/player/{playerid}/chat`,
            {
                json: {
                    "message": {
                        "messageBody": "a".repeat(101)  // Testing for more than 100 characters
                    }
                },
                timeout: 100
            }
        );

        expect(res2.statusCode).toBe(400);
        const bodyObj2 = JSON.parse(res2.body as string);
        expect(bodyObj2).toStrictEqual({
            error: 'Message body is less than 1 character or more than 100 characters'
        });
    });

});
